from fastapi import APIRouter
from fastapi.exceptions import HTTPException
from pydantic import BaseModel, field_validator, Field
from app.models.models import *
from utils.utils import (
    get_first_sentence,
    get_two_consecutive_sentence,
    get_first_sentence_list,
    get_sentence_list,
    remove_parentheses,
)
import random
import re

poem = APIRouter()


# 获取一页古诗的类型校验
class PagePoem(BaseModel):
    page: int = Field(default=1, gt=0, lt=1000)
    num: int = Field(gt=0, lt=1000)


# 获取1页古诗
@poem.post("/page", summary="获取一页古诗")
async def post_page_poems(page_poem: PagePoem):
    """
    根据请求的页数和每页数量，返回相应的古诗列表。

    参数:
    - page_poem: 包含请求页数和每页数量的模型。

    返回:
    - 包含古诗信息的字典，包括id、名称、作者和内容，并进行了特定的处理。
    """
    # 提取页数和每页数量
    page = page_poem.page
    num = page_poem.num
    # 打印页数和每页数量，用于调试
    print(page, num)

    # 从数据库中获取指定页数和数量的古诗
    poems = (
        await Poem.all()
        .offset((page - 1) * num)
        .limit(num)
        .values("id", "name", "author", "content")
    )

    # 遍历古诗列表，对每首古诗的内容和作者进行处理
    for poem in poems:
        # 移除内容中的括号
        poem["content"] = remove_parentheses(poem["content"])
        # 获取内容中的两句连续诗句
        poem["two_sentence"] = get_two_consecutive_sentence(poem["content"])
        # 移除作者名称中的括号
        poem["author"] = remove_parentheses(poem["author"])

    # 返回成功响应，包含处理后的古诗列表
    return {
        "msg": "ok",
        "data": {"poems": poems},
        "code": 200,
    }


# 获取随机1首古诗
@poem.get("/random", summary="获取随机1首古诗")
async def get_random_poem():
    """
    获取数据库中随机一首古诗的信息，包括诗的内容、作者、朝代等，
    并从中提取出推荐的两句连续诗句和第一句诗句用于首页推荐。
    
    Returns:
        dict: 包含古诗信息、推荐的两句连续诗句和第一句诗句的字典。
    """
    # 获取起始和结束id
    start_num = await Poem.all().first().values("id")
    last_num = await Poem.all().last().values("id")
    # 随机获取id
    random_num = random.randint(start_num["id"] + 1, last_num["id"] - 1)
    # 获取随机古诗
    random_poem = await Poem.filter(id=random_num).first().values(
        "id", "name", "author", "dynasty", "content"
    )
    content: str = random_poem.pop("content")
    # 去掉content中的括号极其内容
    content: str = remove_parentheses(content)
    random_poem["author"] = remove_parentheses(random_poem["author"])

    # 推荐诗
    two_sentence: str = get_two_consecutive_sentence(content)

    # 首页推荐诗
    first_sentence: str = get_first_sentence(two_sentence)
    first_sentence: str = get_first_sentence_list(first_sentence)
    return {
        "msg": "ok",
        "data": {
            "poem": random_poem,
            "two_sentence": two_sentence,
            "first_sentence": first_sentence,
        },
        "code": 200,
    }


# 通过id获取古诗详细信息
@poem.post("/poem/", summary="通过id获取古诗详细信息")
async def get_poem_by_id(id: int):
    """
    根据提供的古诗ID，获取古诗的详细信息。
    
    Args:
        id (int): 古诗的唯一标识符。
        
    Raises:
        HTTPException: 如果找不到指定ID的古诗，则抛出404错误。
    """
    # 查询数据库中指定id的古诗详细信息
    poem = await Poem.filter(id=id).values()

    # 如果没有找到古诗，抛出HTTP异常
    if not poem:
        raise HTTPException(
            status_code=404,
            detail={
                "msg": "古诗不存在",
                "code": 404,
            },
        )

    # 取出查询结果中的第一条记录
    poem = poem[0]
    # 移除创建时间字段
    poem.pop("created_at")
    # 处理注释字段，移除括号并拆分成句
    annotation: str = poem.pop("annotation")
    annotation = remove_parentheses(annotation)
    annotation = get_sentence_list(annotation)
    poem["annotation"] = annotation
    # 处理古诗内容字段，移除括号并拆分成句
    poem["content"] = remove_parentheses(poem["content"])
    poem["content"] = get_sentence_list(poem["content"])
    # 处理作者字段，移除括号
    poem["author"] = remove_parentheses(poem["author"])

    # 返回古诗详细信息
    return {
        "msg": "ok",
        "data": {"poem": poem},
        "code": 200,
    }


# 校验古诗id和用户id输入
class PoemIdAndUserId(BaseModel):
    poem_id: int = Field(gt=0, lt=1000000)
    user_id: int = Field(gt=0, lt=1000000)


# 通过古诗id和用户id获取收藏状态
@poem.post("/poem/like", summary="通过古诗id和用户id获取点赞状态")
async def get_like_status(data: PoemIdAndUserId):
    """
    根据古诗ID和用户ID获取点赞状态。
    
    参数:
    - data: PoemIdAndUserId类型，包含poem_id和user_id。
    
    返回:
    - 点赞状态（is_liked）。
    """
    # 从请求数据中获取古诗ID和用户ID
    poem_id = data.poem_id
    user_id = data.user_id
    
    # 先获取具体的诗歌对象
    poem = await Poem.get_or_none(id=poem_id)
    # 如果诗歌不存在，则抛出404异常
    if not poem:
        raise HTTPException(status_code=404, detail="诗歌不存在")

    # 获取点赞状态
    is_liked = await poem.likes.filter(id=user_id).exists()

    # 返回点赞状态信息
    return {
        "msg": "ok",
        "data": {
            "is_liked": is_liked,
        },
        "code": 200,
    }


# 通过古诗id和用户id收藏古诗
@poem.post("/poem/collect", summary="通过古诗id和用户id收藏古诗")
async def collect_poem(data: PoemIdAndUserId):
    """
    收藏古诗。

    参数:
    - data: 包含古诗ID和用户ID的数据对象。

    返回:
    - 成功时返回 {"msg": "ok", "code": 200}
    - 失败时抛出 HTTPException，状态码为404，提示古诗或用户不存在。
    """
    # 从请求数据中提取古诗ID和用户ID
    poem_id = data.poem_id
    user_id = data.user_id

    # 获取古诗和用户对象
    poem = await Poem.get_or_none(id=poem_id)
    user = await User.get_or_none(id=user_id)

    # 校验古诗和用户是否存在
    if not poem or not user:
        # 如果古诗或用户不存在，抛出HTTP异常
        raise HTTPException(
            status_code=404,
            detail={
                "msg": "古诗或用户不存在",
                "code": 404,
            },
        )

    # 添加关联关系，用户收藏古诗
    await poem.likes.add(user)

    # 返回成功响应
    return {
        "msg": "ok",
        "code": 200,
    }


# 通过古诗id和用户id取消收藏古诗
@poem.post("/poem/uncollect", summary="通过古诗id和用户id取消收藏古诗")
async def uncollect_poem(data: PoemIdAndUserId):
    """
    取消用户对某首古诗的收藏。

    此函数接收一个包含古诗ID和用户ID的数据对象，验证古诗和用户是否存在。
    如果存在，则取消用户对这首古诗的收藏。

    参数:
    - data: PoemIdAndUserId类型，包含需要取消收藏的古诗ID和用户ID。

    返回:
    - 成功取消收藏后返回一个包含状态消息"ok"和状态码200的字典。
    """
    # 提取古诗ID和用户ID
    poem_id = data.poem_id
    user_id = data.user_id

    # 异步获取指定ID的古诗和用户对象，如果不存在则返回None
    poem = await Poem.get_or_none(id=poem_id)
    user = await User.get_or_none(id=user_id)

    # 检查古诗和用户是否存在，如果任一不存在则抛出HTTP异常
    if not poem or not user:
        raise HTTPException(
            status_code=404,
            detail={
                "msg": "用户id或古诗id不存在",
                "code": 404,
            },
        )

    # 异步更新数据库，取消用户对古诗的收藏
    await poem.likes.remove(user)
    # 返回成功响应
    return {
        "msg": "ok",
        "code": 200,
    }


# 用户id校验
class UserIdIn(BaseModel):
    user_id: int = Field(gt=0, lt=1000000)


# 通过用户id查找用户收藏的所有古诗
@poem.post("/poem/collect/all", summary="通过用户id查找用户收藏的所有古诗")
async def get_collect_poem(userI: UserIdIn):
    """
    根据用户ID获取用户收藏的所有古诗。

    参数:
    - userI (UserIdIn): 包含用户ID的输入模型。

    返回:
    - 一个包含用户收藏古诗信息的字典。
    """
    # 获取用户ID
    user_id = userI.user_id
    # 根据用户ID获取用户对象，如果不存在则返回None
    user = await User.get_or_none(id=user_id)
    # 检查用户ID是否存在
    if not user_id:
        # 如果用户ID不存在，抛出HTTP异常
        raise HTTPException(
            status_code=404,
            detail={
                "msg": "用户id不存在",
            },
        )

    # 使用 values() 来选择需要的字段
    poems = await user.poems.all().values("id", "name", "author", "content")

    # 处理content字段
    for poem in poems:
        # 移除content中的括号内容
        content = poem.pop("content")
        content = remove_parentheses(content)
        # 提取content中的两句连续诗句
        poem["two_sentence"] = get_two_consecutive_sentence(content)
        # 移除作者名中的括号内容
        poem["author"] = remove_parentheses(poem["author"])

    # 返回用户收藏的古诗信息
    return {
        "msg": "ok",
        "data": {
            "poems": poems,
        },
        "code": 200,
    }
